#ifndef AUDIOCAPTURER_H
#define AUDIOCAPTURER_H

#include <QThread>
#include <QVector>
#include <atomic>
#include <windows.h>
#include <mmdeviceapi.h>  // Windows Multimedia Device API
#include <audioclient.h>  // Windows Audio Client API

// 前置声明，避免循环依赖
class SpectrumAnalyzer;

/**
 * @class AudioCapturer
 * @brief 音频捕获类 - 使用 Windows WASAPI 捕获系统音频输出
 * 
 * 继承自 QThread，在独立线程中运行音频捕获，避免阻塞主线程 UI
 * 使用 WASAPI Loopback 模式捕获系统正在播放的音频（不是从麦克风录音）
 */
class AudioCapturer : public QThread
{
    Q_OBJECT

public:
    /**
     * @brief 构造函数
     * @param parent 父对象指针
     * 
     * 初始化所有成员变量为 nullptr 或初始状态
     * 注意：COM 初始化在 run() 方法中进行，而不是这里
     */
    explicit AudioCapturer(QObject *parent = nullptr);
    
    /**
     * @brief 析构函数
     * 
     * 停止音频捕获，等待线程结束
     * COM 清理在 run() 方法中完成
     */
    ~AudioCapturer();

    /**
     * @brief 停止音频捕获
     * 
     * 设置停止标志，通知捕获循环退出
     * 线程安全：使用 atomic 变量
     */
    void stopCapture();
    
    /**
     * @brief 检查是否正在捕获
     * @return true 表示正在捕获，false 表示已停止
     * 
     * 线程安全：使用 atomic 变量
     */
    bool isCapturing() const { return m_isCapturing; }

signals:
    /**
     * @brief 频谱数据就绪信号
     * @param spectrum 频谱数组（20个频段，范围 0.0-1.0）
     * 
     * 当FFT分析完成后发出，直接发送频谱数据到主线程UI
     * 注意：FFT在子线程中执行
     */
    void spectrumReady(const QVector<float> &spectrum);
    
    /**
     * @brief 错误发生信号
     * @param error 错误描述信息
     * 
     * 当初始化或捕获过程中发生错误时发出
     */
    void errorOccurred(const QString &error);

protected:
    /**
     * @brief 线程主函数（重写 QThread::run）
     * 
     * 执行流程：
     * 1. 初始化 COM（组件对象模型）
     * 2. 初始化 WASAPI 音频捕获
     * 3. 进入捕获循环
     * 4. 清理资源并反初始化 COM
     * 
     * 所有 WASAPI 调用都在此线程中完成
     */
    void run() override;

private:
    /**
     * @brief 初始化 WASAPI 音频捕获
     * @return true 表示成功，false 表示失败
     * 
     * 步骤：
     * 1. 创建设备枚举器
     * 2. 获取默认音频输出设备（扬声器/耳机）
     * 3. 激活音频客户端
     * 4. 获取音频格式信息
     * 5. 以 Loopback 模式初始化音频客户端
     * 6. 获取捕获客户端接口
     * 7. 启动音频流
     */
    bool initializeWASAPI();
    
    /**
     * @brief 清理 WASAPI 资源
     * 
     * 按照与初始化相反的顺序释放所有 COM 接口和内存
     * 必须在同一线程中调用（与初始化相同的线程）
     */
    void cleanupWASAPI();
    
    /**
     * @brief 音频捕获循环
     * 
     * 持续从音频缓冲区读取数据，直到收到停止请求
     * 处理流程：
     * 1. 检查是否有新的音频包
     * 2. 读取音频缓冲区
     * 3. 转换音频格式（多声道→单声道，整数→浮点）
     * 4. 发送 audioDataReady 信号
     * 5. 释放缓冲区
     */
    void captureLoop();

    // WASAPI 相关的 COM 接口指针
    IMMDeviceEnumerator *m_deviceEnumerator;  ///< 设备枚举器，用于查找音频设备
    IMMDevice *m_device;                      ///< 音频设备接口
    IAudioClient *m_audioClient;              ///< 音频客户端，用于配置和控制音频流
    IAudioCaptureClient *m_captureClient;     ///< 音频捕获客户端，用于读取音频数据
    WAVEFORMATEX *m_waveFormat;               ///< 音频格式信息（采样率、声道数、位深度等）

    // 频谱分析相关（在子线程中使用）
    SpectrumAnalyzer *m_spectrumAnalyzer;     ///< 频谱分析器，在子线程中创建和使用
    QVector<float> m_audioBuffer;             ///< 音频数据缓冲区（累积约0.5秒的数据）
    int m_sampleRate;                         ///< 当前采样率（Hz）

    // 状态标志（使用 atomic 保证线程安全）
    std::atomic<bool> m_isCapturing;     ///< 是否正在捕获音频
    std::atomic<bool> m_stopRequested;   ///< 是否请求停止捕获
};

#endif // AUDIOCAPTURER_H